package ar.edu.unq.edp.futbol.mains;

import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.CyclicBarrier;

import javax.management.RuntimeErrorException;

import org.hibernate.SessionFactory;
import org.hibernate.Transaction;
import org.hibernate.cfg.Configuration;
import org.hibernate.classic.Session;
import org.hibernate.criterion.Restrictions;

import persistencia.EquipoBuilder;
import unq.equipos.dom.Equipo;
import unq.equipos.dom.FormacionStrategy;
import unq.equipos.dom.FormacionStrategyImpl;
import unq.equipos.dom.Posicion;
import unq.equipos.dom.Tecnico;
import unq.equipos.dom.partidos.Partido;
import unq.equipos.dom.partidos.PartidoCopa;
import unq.equipos.dom.partidos.PartidoSimple;

public class InsertPartido implements Runnable{
	private CyclicBarrier barrier;
	
	public InsertPartido(CyclicBarrier barrier) {
		this.setBarrier(barrier);
	}
	
	/**
	 * Crea un partido simple y setea los goles pasados por parametro
	 * @param golesEquipoIndependiente
	 * @param golesEquipoRacing
	 * @return
	 */
	public static Partido mkPartidoSimple(int golesEquipoIndependiente, int golesEquipoRacing){
		List<Posicion> posiciones = new ArrayList<Posicion>();
		posiciones.add(Posicion.Arquero);
		posiciones.add(Posicion.Lateral);
		posiciones.add(Posicion.Lateral);
		posiciones.add(Posicion.Central);
		posiciones.add(Posicion.Central);
		posiciones.add(Posicion.VolanteDefensivo);
		posiciones.add(Posicion.VolanteLateral);
		posiciones.add(Posicion.VolanteLateral);
		posiciones.add(Posicion.Enganche);
		posiciones.add(Posicion.Delantero);
		posiciones.add(Posicion.MediaPunta);
		FormacionStrategy estrategia = new FormacionStrategyImpl(posiciones);
		
		Tecnico tecnicoIndependiente = new Tecnico ("Mohamed Ali");
		Equipo independiente = new EquipoBuilder().mkBigTeam("Independiente", tecnicoIndependiente);
		tecnicoIndependiente.setFormacionStrategy(estrategia);
		
		Tecnico tecnicoRacing = new Tecnico("Russo"); 
		Equipo racing = new EquipoBuilder().mkNormalTeam("Racing", tecnicoRacing);
		tecnicoRacing.setFormacionStrategy(estrategia);
		
		PartidoSimple partido = new PartidoSimple(independiente, independiente.armarFormacion(),
								racing, racing.armarFormacion());
		
		partido.setGolesEquipoLocal(golesEquipoIndependiente);
		partido.setGolesEquipoVisitante(golesEquipoRacing);
		
		return partido;
	}
	
	public static Partido mkPartidoSimpleDos(int golesEquipoIndependiente, int golesEquipoRacing){
		List<Posicion> posiciones = new ArrayList<Posicion>();
		posiciones.add(Posicion.Arquero);
		posiciones.add(Posicion.Lateral);
		posiciones.add(Posicion.Lateral);
		posiciones.add(Posicion.Central);
		posiciones.add(Posicion.Central);
		posiciones.add(Posicion.VolanteDefensivo);
		posiciones.add(Posicion.VolanteLateral);
		posiciones.add(Posicion.VolanteLateral);
		posiciones.add(Posicion.Enganche);
		posiciones.add(Posicion.Delantero);
		posiciones.add(Posicion.MediaPunta);
		FormacionStrategy estrategia = new FormacionStrategyImpl(posiciones);
		
		Tecnico tecnicoIndependiente = new Tecnico ("Mohamed Ali");
		Equipo independiente = new EquipoBuilder().mkBigTeam("Independiente", tecnicoIndependiente);
		tecnicoIndependiente.setFormacionStrategy(estrategia);
		
		Tecnico tecnicoRacing = new Tecnico("Russo"); 
		Equipo racing = new EquipoBuilder().mkNormalTeam("Racing", tecnicoRacing);
		tecnicoRacing.setFormacionStrategy(estrategia);
		
		PartidoSimple partido = new PartidoSimple(racing, racing.armarFormacion(),
				independiente, independiente.armarFormacion());
		
		partido.setGolesEquipoLocal(golesEquipoRacing);
		partido.setGolesEquipoVisitante(golesEquipoIndependiente);
		
		return partido;
	}
	
	public static Partido mkPartidoCopa(){
		Partido partidoUno = InsertPartido.mkPartidoSimple(3, 1);
		Partido partidoDos = InsertPartido.mkPartidoSimpleDos(2, 0);
		
		PartidoCopa partidoCopa = new PartidoCopa();
		partidoCopa.setPartidoUno((PartidoSimple) partidoUno);
		partidoCopa.setPartidoDos((PartidoSimple) partidoDos);
		
		partidoCopa.setGolesPenalEquipoDos(2);
		partidoCopa.setGolesPenalEquipoUno(4);
		return partidoCopa;
	}
	
	public void run() {
		Partido partido = InsertPartido.mkPartidoCopa();
		Class<PartidoCopa> partidoClass = PartidoCopa.class;
		
		// Esta instancia es thread safe
		SessionFactory sessionFactory = new Configuration().configure()
				.buildSessionFactory();

		// esta ya no es threadSafe
		Session session = sessionFactory.openSession();
		Transaction transaction = session.beginTransaction();
		int partidoId;
		
		
		try {
			System.out.println("Entro en el barrier");
			barrier.await();
			System.out.println("Salio del barrier");
			session.save(partido);
			transaction.commit();
			partidoId = partido.getId();

			partido = null;
			System.gc();
			
			Partido unPartido = (Partido)session.createCriteria(partidoClass)
			.add(Restrictions.idEq(partidoId))
			.uniqueResult();
			System.out.println("gano: "+unPartido.equipoGanador().getNombre());
		} catch (RuntimeException e) {
			transaction.rollback();
			throw e;
		} catch (Exception e){
			throw new RuntimeException();
		} finally {
			session.close();
		}
	}

	public void setBarrier(CyclicBarrier barrier) {
		this.barrier = barrier;
	}

	public CyclicBarrier getBarrier() {
		return barrier;
	}
}
